defmodule SockWorkstation.SockASRClient do
  use WebSockex

  # WebSocket 服务器地址
  # @token "coop-token"
  # @url "wss://72-j.cn:5179/xiaozhi/coop?token=#{@token}"
  # 保活间隔（30 秒）
  # @keepalive_interval 30_000

  # alias SockWorkstation.{
  #   CoopMgrGen
  # }

  @url "wss://dashscope.aliyuncs.com/api-ws/v1/inference/"
  # @audio_file "12.opus"
  @api_key "sk-16df948259d347f7a31c67e314c1a8fc"
  @match_tokens [
    ~c"吗",
    ~c"嘛",
    ~c"么",
    ~c"呢",
    ~c"吧",
    ~c"啦",
    ~c"\\？",
    ~c"\\?",
    ~c"拜拜",
    ~c"再见",
    ~c"晚安",
    ~c"退下"
  ]
  @regex_pattern Regex.compile!(Enum.join(@match_tokens, "|"), "u")

  def start_link(session_id) do
    WebSockex.start_link(@url, __MODULE__, %{session_id: session_id},
      extra_headers: headers()
    )
  end

  defp headers do
    [
      {"Authorization", "bearer #{@api_key}"},
      {"X-DashScope-DataInspection", "enable"}
    ]
  end

  @impl WebSockex
  def handle_connect(_conn, state) do
    IO.puts("Asr WebSocket Connected!")

    self_pid = self()
    # CoopMgrGen.add_asr_pid(state.session_id, self_pid)
    Process.send_after(self_pid, :run_asr_task, 120)
    state =
      state
      |> Map.put(:self_pid, self_pid)
      |> Map.put(:asr_task_id, "")
      |> Map.put(:str_buffer, "")
      |> Map.put(:bin_buffer, <<>>)
      |> Map.put(:chunk_num, 0)
      |> Map.put(:last_processed, System.system_time(:millisecond))

    # send_run_task(self(), @asr_task_id)
    {:ok, state}
  end

  def send_asr_task(pid, pcm_data) do
    # Process.sleep(200)  # 每 100ms 发送一次
    WebSockex.send_frame(pid, {:binary, pcm_data})
    # send(pid, {:audio_chunk, pcm_data})
  end

  @impl WebSockex
  def handle_frame({:text, message}, state) do
    message = Jason.decode!(message)

    case message["header"]["event"] do
      "task-started" ->
        IO.puts("asr task started")
        # send_audio_stream(self(), @audio_file)
        SockWorkstation.ASRHelperGen.starting_asr(state.session_id, state.self_pid)
        {:ok, Map.put(state, :task_started, true)}

      "result-generated" ->

        send(
          state.self_pid,
          {:asr_resp, message["payload"]["output"]["sentence"]["text"]}
        )

        # end
        {:ok, state}

      "task-finished" ->
        IO.puts("asr task finished")
        # send(CoopMgrGen.get_state(state.session_id).coop_mgr_pid, :run_sent_tts)
        # SockWorkstation.SockCoopClient.send_speaking(
        #   SockWorkstation.CoopMgrGen.get_state(state.session_id).coop_pid
        # )
        SockWorkstation.ASRHelperGen.stopping_asr(state.session_id)
        Process.send_after(state.self_pid, :task_finished, 500)
        {:ok, state}

      "task-failed" ->
        IO.puts("asr task failed: #{message["header"]["error_message"]}")
        {:close, state}

      _ ->
        IO.puts("something wrong with events: #{message["header"]["event"]}")
        {:ok, state}
    end
  end

  @impl true
  def handle_info(:run_asr_task, state) do
    asr_task_id = UUID.uuid4(:hex)
    run_task_message = %{
      header: %{
        action: "run-task",
        task_id: asr_task_id,
        streaming: "duplex"
      },
      payload: %{
        task_group: "audio",
        task: "asr",
        function: "recognition",
        model: "paraformer-realtime-v1",
        parameters: %{
          sample_rate: 16000,
          format: "pcm"
        },
        input: %{}
      }
    }


    {:reply, {:text, Jason.encode!(run_task_message)}, state|> Map.put(:asr_task_id, asr_task_id)}

  end

  def handle_info(:finish_asr_task, state) do
    finish_task_message = %{
      header: %{
        action: "finish-task",
        task_id: state.asr_task_id,
        streaming: "duplex"
      },
      payload: %{
        input: %{}
      }
    }

    {:reply, {:text, Jason.encode!(finish_task_message)}, state}

  end


  # def handle_info({:audio_chunk, chunk}, state) do
  #   #  IO.puts("Received audio chunk: #{inspect(byte_size(chunk))}")
  #   # bin_buffer = [chunk | state.bin_buffer]
  #   bin_buffer = <<state.bin_buffer::binary, chunk::binary>>

  #     {:reply, {:binary, bin_buffer}, %{state | chunk_num: 0, bin_buffer: <<>>}}

  # end

  def handle_info({:asr_resp, result}, state) do
    now = System.system_time(:millisecond)
    IO.puts("识别：#{result}")
    str_buffer = state.str_buffer <> result
    IO.puts("buffer：#{str_buffer}")

    # 限制每200毫秒处理一次
    if now - state.last_processed > 200 do
      if contains_tokens?(result) do
        SockWorkstation.CoopMgrGen.run_asr_result(state.session_id, str_buffer)
        send(state.self_pid, :finish_asr_task)
        # Process.send_after(state.self_pid, :finish_asr_task, 200)

      end

      {:ok, %{state | str_buffer: str_buffer, last_processed: now}}
    else
      {:ok, state}
    end

  end


  def handle_info(:task_finished, state) do

    {:close, state}
  end


  @impl WebSockex
  def handle_disconnect(_conn, state) do

    {:ok, state}
  end

  def contains_tokens?(message) do
    Regex.match?(@regex_pattern, message)
  end

  # @impl true
  # def terminate(_reason, state) do
  #   # CoopMgrGen.rm_asr_pid(state.session_id)

  #   # IO.puts("\nASR Socket Terminating:\n#{inspect(reason)}\n\n#{inspect(state)}\n")
  #   # exit(:normal)
  # end
end

# def handle_info(:close, state) do
#   # 关闭连接
#   IO.puts("关闭连接")

#   # WebSockex.send_frame(self(), {:close, 1000, "Recognition complete"})
#   {:close, state}
# end

# defp send_audio_stream() do
#   case File.read(@audio_file) do
#     {:ok, audio_data} ->
#       # 将音频数据分块发送
#       # 每块 1024 字节
#       chunks = chunk_data(audio_data, 1024)

#       Enum.each(chunks, fn chunk ->
#         # 每 100ms 发送一次
#         Process.sleep(100)
#         send(CoopMgrGen.get_state().asr_pid, {:send_audio_chunk, chunk})
#       end)

#       send(CoopMgrGen.get_state().asr_pid, :send_finish_task)

#     {:error, reason} ->
#       IO.puts("读取音频文件错误：#{reason}")
#       WebSockex.terminate(CoopMgrGen.get_state().asr_pid)
#   end
# end

# defp chunk_data(data, chunk_num) do
#   for <<chunk::binary-size(chunk_num) <- data>>, do: chunk
# end



  # def send_run_task(pid, asr_task_id) do
  #   run_task_message = %{
  #     header: %{
  #       action: "run-task",
  #       asr_task_id: asr_task_id,
  #       streaming: "duplex"
  #     },
  #     payload: %{
  #       task_group: "audio",
  #       task: "asr",
  #       function: "recognition",
  #       model: "paraformer-realtime-v1",
  #       parameters: %{
  #         sample_rate: 16000,
  #         format: "pcm"
  #       },
  #       input: %{}
  #     }
  #   }

  #   WebSockex.send_frame(pid, {:text, Jason.encode!(run_task_message)})
  # end

  # def send_finish_task(pid, asr_task_id) do
  #   finish_task_message = %{
  #     header: %{
  #       action: "finish-task",
  #       asr_task_id: asr_task_id,
  #       streaming: "duplex"
  #     },
  #     payload: %{
  #       input: %{}
  #     }
  #   }

  #   WebSockex.send_frame(pid, {:text, Jason.encode!(finish_task_message)})
  # end
